const express = require('express');
const moment = require('moment');
const rongCloud = require('rongcloud-sdk');
const Config = require('config');
const co = require('co');
const logger = require('flogger').getLogger();

const Session = require('../util/session');
const Utility = require('../util/util').Utility;
const APIResult = require('../util/util').APIResult;

const db = require('../models');
const sequelize = db.sequelize;
const User = db.User;
const Blacklist = db.Blacklist;
const Friendship = db.Friendship;

const FRIENDSHIP_REQUESTING = 10;
const FRIENDSHIP_REQUESTED = 11;
const FRIENDSHIP_AGREED = 20;
const FRIENDSHIP_IGNORED = 21;
const FRIENDSHIP_DELETED = 30;
const FRIEND_REQUEST_MESSAGE_MIN_LENGTH = 0;
const FRIEND_REQUEST_MESSAGE_MAX_LENGTH = 64;
const FRIEND_DISPLAY_NAME_MIN_LENGTH = 1;
const FRIEND_DISPLAY_NAME_MAX_LENGTH = 32;
const CONTACT_OPERATION_ACCEPT_RESPONSE = 'AcceptResponse';
const CONTACT_OPERATION_REQUEST = 'Request';

rongCloud.init(Config.RONGCLOUD_APP_KEY, Config.RONGCLOUD_APP_SECRET);

var router = express.Router();

var validator = sequelize.Validator;
/**
 * @api {post} /webim/friendship/add 添加好友
 * @apiName AddFriend
 * @apiGroup FriendShip
 * @apiVersion 0.1.0
 *
 * @apiParam {String} friendId 好友ID
 *
 * @apiSuccessExample 成功响应:
 *    HTTP/1.1 200 OK
 *    {
 *       "code": 200
 *     }
 */
router.post('/add', function (req, res, next) {
  let friendId = req.body.friendId;
  let currentUserId = Session.getCurrentUserId(req);
  let timestamp = Date.now();

  // 邀请 + 同意
  co(function*() {
    var result = yield invite(currentUserId, friendId, '系统添加');

    if (result.action == 'None') {
      return res.send(new APIResult(400, {
        action: 'None'
      }, result.message));
    }

    logger.info('%s 添加用户 -> %s', currentUserId, friendId);

    return sequelize.transaction(function (t) {
      return Friendship.update({
        status: FRIENDSHIP_AGREED,
        timestamp: timestamp
      }, {
        where: {
          userId: friendId,
          friendId: currentUserId,
          status: FRIENDSHIP_REQUESTED
        },
        transaction: t
      }).then(function (arg) {
        var affectedCount;
        affectedCount = arg[0];
        if (affectedCount === 0) {
          return res.status(404).send('Unknown friend user or invalid status.');
        }
        return Friendship.update({
          status: FRIENDSHIP_AGREED,
          timestamp: timestamp
        }, {
          where: {
            userId: currentUserId,
            friendId: friendId
          },
          transaction: t
        }).then(function () {
          return res.send(new APIResult(200));
        });
      });
    }).catch(next);
  });
});

router.post('/set_display_name', function (req, res, next) {
  var currentUserId, displayName, friendId, timestamp;
  friendId = req.body.friendId;
  displayName = Utility.xss(req.body.displayName, FRIEND_REQUEST_MESSAGE_MAX_LENGTH);
  if ((displayName !== '') && !validator.isLength(displayName, FRIEND_DISPLAY_NAME_MIN_LENGTH, FRIEND_DISPLAY_NAME_MAX_LENGTH)) {
    return res.status(400).send('Length of displayName is out of limit.');
  }
  currentUserId = Session.getCurrentUserId(req);
  timestamp = Date.now();
  return Friendship.update({
    displayName: displayName,
    timestamp: timestamp
  }, {
    where: {
      userId: currentUserId,
      friendId: friendId,
      status: FRIENDSHIP_AGREED
    }
  }).then(function (arg) {
    var affectedCount;
    affectedCount = arg[0];
    if (affectedCount === 0) {
      return res.status(404).send('Unknown friend user or invalid status.');
    }
    return res.send(new APIResult(200));
  }).catch(next);
});


/**
 * @api {get} /webim/friendship/all 获取当前登录用户的所有好友列表
 * @apiName GetAllFriends
 * @apiGroup FriendShip
 * @apiVersion 0.1.0
 *
 * @apiSuccessExample 成功响应:
 *    HTTP/1.1 200 OK
 *    {
 *      "code": 200,
 *      "result": [
 *        {
 *          "displayName": "",
 *          "message": "系统添加",
 *          "status": 20,
 *          "updatedAt": "2016-09-12T02:14:04.000Z",
 *          "user": {
 *            "id": "6K3EdJh9C",
 *            "uid": "zhangdc",
 *            "nickname": "张德聪",
 *            "contactNumber": "18688780069",
 *            "storeName": "开思",
 *            "storeId": "SUPER007",
 *            "partyGroup": "张德聪",
 *            "portraitUri": ""
 *          }
 *        },
 *        {
 *          "displayName": "",
 *          "message": "系统添加",
 *          "status": 20,
 *          "updatedAt": "2016-09-13T07:45:04.000Z",
 *          "user": {
 *            "id": "yLaqAmlHi",
 *            "uid": "kswz",
 *            "nickname": "王志",
 *            "contactNumber": "18688780069",
 *            "storeName": "开思",
 *            "storeId": "SUPER007",
 *            "partyGroup": "王志",
 *            "portraitUri": ""
 *          }
 *        },
 *        ...
 *      ]
 *    }
 */
router.get('/all', function (req, res, next) {
  let userId = Session.getCurrentUserId(req);
  co(function*() {
    let friends = yield  Friendship.findAll({
      where: {
        userId: userId
      },
      attributes: ['displayName', 'message', 'status', 'updatedAt'],
      include: {
        model: User,
        as: 'user',
        attributes: ['id', 'uid', 'nickname', 'contactNumber', 'storeName', 'storeId', 'partyGroup', 'portraitUri']
      }
    });
    logger.info(`${userId} 查找所有好友`);
    return res.send(new APIResult(200, Utility.encodeResults(friends, [['user', 'id']])));
  }).catch(err => {
    logger.warn(`${userId} 查找好友失败`, err);
    return next(err);
  });
});

router.get('/:id/profile', function (req, res, next) {
  var userId;
  userId = req.params.id;
  userId = Utility.decodeIds(userId);
  return Friendship.findOne({
    where: {
      userId: Session.getCurrentUserId(req),
      friendId: userId,
      status: FRIENDSHIP_AGREED
    },
    attributes: ['displayName'],
    include: {
      model: User,
      attributes: ['id', 'uid', 'nickname', 'region', 'contactNumber', 'portraitUri']
    }
  }).then(function (friend) {
    if (!friend) {
      return res.status(403).send("Current user is not friend of user " + userId + ".");
    }
    return res.send(new APIResult(200, Utility.encodeResults(friend, [['user', 'id']])));
  }).catch(next);
});


function invite(currentUserId, friendId, message) {

  if (!validator.isLength(message, FRIEND_REQUEST_MESSAGE_MIN_LENGTH, FRIEND_REQUEST_MESSAGE_MAX_LENGTH)) {
    return Promise.reject({
      status: 400,
      body: 'Length of friend request message is out of limit.'
    });
  }

  var timestamp = Date.now();
  logger.info('%s invite user -> %s', currentUserId, friendId);

  return Promise.all([
    Friendship.getInfo(currentUserId, friendId), Friendship.getInfo(friendId, currentUserId), Blacklist.findOne({
      where: {
        userId: friendId,
        friendId: currentUserId
      },
      attributes: ['status']
    })
  ]).then(function (arg) {
    var action, blacklist, fd, fdStatus, fg, fgStatus, resultMessage, unit;
    fg = arg[0], fd = arg[1], blacklist = arg[2];
    Utility.log('Friendship requesting: %j', fg);
    Utility.log('Friendship requested:  %j', fd);
    if (blacklist && blacklist.status) {
      Utility.log('Invite result: %s %s', 'None: blacklisted by friend', 'Do nothing.');
      return {
        action: 'None',
        message: 'In blacklist'
      };
    }
    action = 'Added';
    resultMessage = 'Friend added.';
    if (fg && fd) {
      if (fg.status === FRIENDSHIP_AGREED && fd.status === FRIENDSHIP_AGREED) {
        throw {
          status: 400,
          body: "User " + friendId + " is already your friend."
        };
      }
      unit = 'd';
      if (fd.status === FRIENDSHIP_REQUESTING) {
        fgStatus = FRIENDSHIP_AGREED;
        fdStatus = FRIENDSHIP_AGREED;
        message = fd.message;
      } else if (fd.status === FRIENDSHIP_AGREED) {
        fgStatus = FRIENDSHIP_AGREED;
        fdStatus = FRIENDSHIP_AGREED;
        message = fd.message;
        timestamp = fd.timestamp;
      } else if ((fd.status === FRIENDSHIP_DELETED && fg.status === FRIENDSHIP_DELETED)
        || (fg.status === FRIENDSHIP_AGREED && fd.status === FRIENDSHIP_DELETED)
        || (fg.status === FRIENDSHIP_REQUESTING && fd.status === FRIENDSHIP_IGNORED && moment().subtract(1, unit).isAfter(fg.updatedAt))
        || (fg.status === FRIENDSHIP_REQUESTING && fd.status === FRIENDSHIP_REQUESTED && moment().subtract(3, unit).isAfter(fg.updatedAt))) {
        fgStatus = FRIENDSHIP_REQUESTING;
        fdStatus = FRIENDSHIP_REQUESTED;
        action = 'Sent';
        resultMessage = 'Request sent.';
      } else {
        Utility.log('Invite result: %s %s', 'None', 'Do nothing.');
        return {
          action: 'None',
          message: 'Do Nothing'
        };
      }

      return sequelize.transaction(function (t) {
        return Promise.all([
          fg.update({
            status: fgStatus,
            timestamp: timestamp
          }, {
            transaction: t
          }), fd.update({
            status: fdStatus,
            timestamp: timestamp,
            message: message
          }, {
            transaction: t
          })
        ]).then(function () {
          if (fd.status === FRIENDSHIP_REQUESTED) {
            Utility.log('Invite result: %s %s', action, resultMessage);
            return {
              action: action,
              message: resultMessage
            };
          } else {
            Utility.log('Invite result: %s %s', action, resultMessage);
            return {
              action: action,
              message: resultMessage
            };
          }
        });
      });
    } else {
      if (friendId === currentUserId) {
        return Friendship.create({
          userId: currentUserId,
          friendId: friendId,
          message: '',
          status: FRIENDSHIP_AGREED,
          timestamp: timestamp
        }).then(function () {
          Utility.log('Invite result: %s %s', action, resultMessage);
          return {
            action: action,
            message: resultMessage
          };
        });
      } else {
        return sequelize.transaction(function (t) {
          return Promise.all([
            Friendship.create({
              userId: currentUserId,
              friendId: friendId,
              message: '',
              status: FRIENDSHIP_REQUESTING,
              timestamp: timestamp
            }, {
              transaction: t
            }), Friendship.create({
              userId: friendId,
              friendId: currentUserId,
              message: message,
              status: FRIENDSHIP_REQUESTED,
              timestamp: timestamp
            }, {
              transaction: t
            })
          ]).then(function () {
            return {
              action: 'Sent',
              message: 'Request sent.'
            };
          });
        });
      }
    }
  });
}


module.exports = router;
